﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace D3crft.Windows.UserControls {
    /// <summary>
    /// Interaktionslogik für ucTabControlAdvanced.xaml
    /// </summary>
    public partial class ucTabControlAdvanced : UserControl {
        public enum eTab { Options, Characters, Item_Comparison, Simulation };

        public event EventHandler evTabSelectionChanged;

        const int ITEM_COUNT = 4;
        const double INDICATOR_MAXSPEED = 30.0;
        const double INDICATOR_ACCELERATION = 1.67;

        private enum eIndicatorAccelerationMode { Accelerate, Deccelerate };

        private eTab eSelectedIndex = eTab.Characters;

        private int[] iItemTransitioning;
        private double[] dItemOpacity;
        private int iIndicatorTargetIndex = 1;
        private double dIndicatorVelocity = 0.0;
        private eIndicatorAccelerationMode eIndicatorMode = eIndicatorAccelerationMode.Deccelerate;
        private double dIndicatorMaxPPT = 0.0;

        DispatcherTimer oGlowTimer;
        DispatcherTimer oIndicatorTimer;


        public ucTabControlAdvanced() {
            InitializeComponent();

            iItemTransitioning = new int[] { 0, 0, 0, 0 };
            dItemOpacity = new double[] { 0.0, 0.5, 0.0, 0.0 };

            oGlowTimer = new DispatcherTimer();
            oGlowTimer.Interval = TimeSpan.FromMilliseconds(40.0);
            oGlowTimer.Tick += new EventHandler(ev_oGlowTimer_Tick);
            oIndicatorTimer = new DispatcherTimer();
            oIndicatorTimer.Interval = TimeSpan.FromMilliseconds(20.0);
            oIndicatorTimer.Tick += new EventHandler(ev_oIndicatorTimer_Tick);
        }


        public eTab get_SelectedTab() {
            return eSelectedIndex;
        }



        private void select_Item(eTab eTab) {
            start_GlowDownByIndex(eSelectedIndex);
            eSelectedIndex = eTab;
            start_GlowUpByIndex(eTab);
            move_IndicatorToIndex(eTab);
            if (evTabSelectionChanged != null) evTabSelectionChanged(this, EventArgs.Empty);
        }

        private void move_IndicatorToIndex(eTab eTab) {
            iIndicatorTargetIndex = (int)eTab;
            eIndicatorMode = eIndicatorAccelerationMode.Accelerate;
            if (!oIndicatorTimer.IsEnabled) oIndicatorTimer.Start();
        }

        private Rectangle get_EffectByIndex(eTab eTab) {
            switch (eTab) {
                case eTab.Options:
                    return Effect_1;
                case eTab.Characters:
                    return Effect_2;
                case eTab.Item_Comparison:
                    return Effect_3;
                case eTab.Simulation:
                    return Effect_4;
                default:
                    return null;
            }
        }

        private void start_GlowUpByIndex(eTab eTab) {
            iItemTransitioning[(int)eTab] = 1;
            if (!oGlowTimer.IsEnabled) oGlowTimer.Start();
        }

        private void start_GlowDownByIndex(eTab eTab) {
            iItemTransitioning[(int)eTab] = 2;
            if (!oGlowTimer.IsEnabled) oGlowTimer.Start();
        }

        private void ev_Item_MouseEnter(object sender, EventArgs ea) {
            int iIndex = (int.Parse((sender as Grid).Name.Split('_')[1]) - 1);

            if (iIndex != (int)eSelectedIndex) {
                start_GlowUpByIndex((eTab)iIndex);
            }
        }

        private void ev_Item_MouseLeave(object sender, EventArgs ea) {
            int iIndex = (int.Parse((sender as Grid).Name.Split('_')[1]) - 1);

            if (iIndex != (int)eSelectedIndex) {
                start_GlowDownByIndex((eTab)iIndex);
            }
        }

        private void ev_Item_MouseUp(object sender, EventArgs ea) {
            int iIndex = (int.Parse((sender as Grid).Name.Split('_')[1]) - 1);

            if (iIndex != (int)eSelectedIndex) {
                select_Item((eTab)iIndex);
            }
        }

        private void ev_oGlowTimer_Tick(object sender, EventArgs ea) {
            bool bTemp = false;

            for (int i = 0; i < ITEM_COUNT; i++) {
                if (iItemTransitioning[i] > 0) {
                    bTemp = true;
                    if (iItemTransitioning[i] == 1) {
                        // glow up
                        dItemOpacity[i] += 0.1;
                        if (dItemOpacity[i] >= 0.5) {
                            dItemOpacity[i] = 0.5;
                            iItemTransitioning[i] = 0;
                        }
                        get_EffectByIndex((eTab)i).Opacity = dItemOpacity[i];
                    } else {
                        // glow down
                        dItemOpacity[i] -= 0.1;
                        if (dItemOpacity[i] <= 0.0) {
                            dItemOpacity[i] = 0.0;
                            iItemTransitioning[i] = 0;
                        }
                        get_EffectByIndex((eTab)i).Opacity = dItemOpacity[i];
                    }
                }
            }
            if (!bTemp) oGlowTimer.Stop();
        }


        private void ev_oIndicatorTimer_Tick(object sender, EventArgs ea) {
            double dTargetLeft = 10 + (iIndicatorTargetIndex * 130);
            double dDistance, dSlowDownDistance;
            bool bModeToRight;
            if (dTargetLeft > Indicator.Margin.Left) {
                dDistance = dTargetLeft - Indicator.Margin.Left;
                bModeToRight = true;
            }
            else {
                dDistance = Indicator.Margin.Left - dTargetLeft;
                bModeToRight = false;
            }

            if (eIndicatorMode == eIndicatorAccelerationMode.Accelerate) {
                // check for decceleration
                dSlowDownDistance = (dIndicatorVelocity / INDICATOR_ACCELERATION) * (dIndicatorVelocity / 2);
                if (dSlowDownDistance >= dDistance) {
                    // slow down!
                    eIndicatorMode = eIndicatorAccelerationMode.Deccelerate;
                }
            }

            if (eIndicatorMode == eIndicatorAccelerationMode.Accelerate) {
                // accelerate mode
                if (dIndicatorVelocity < INDICATOR_MAXSPEED) {
                    // accelerate some more
                    dIndicatorVelocity += INDICATOR_ACCELERATION;
                    if (dIndicatorVelocity >= INDICATOR_MAXSPEED) dIndicatorVelocity = INDICATOR_MAXSPEED;
                }
                // move it!
                if (bModeToRight) {
                    Indicator.Margin = new Thickness(Indicator.Margin.Left + dIndicatorVelocity, Indicator.Margin.Top, Indicator.Margin.Right, Indicator.Margin.Bottom);
                }
                else {
                    Indicator.Margin = new Thickness(Indicator.Margin.Left - dIndicatorVelocity, Indicator.Margin.Top, Indicator.Margin.Right, Indicator.Margin.Bottom);
                }
            }
            else {
                // deccelerate mode
                if (dDistance == 0.0) {
                    oIndicatorTimer.Stop();
                    dIndicatorVelocity = 0.0;
                }
                else {
                    if (dIndicatorVelocity > INDICATOR_ACCELERATION) {
                        // deccelerate some more
                        dIndicatorVelocity -= INDICATOR_ACCELERATION;
                        if (dIndicatorVelocity < INDICATOR_ACCELERATION) dIndicatorVelocity = INDICATOR_ACCELERATION;
                    }
                    // move it!
                    if ((dDistance - dIndicatorVelocity) < 0.0) {
                        Indicator.Margin = new Thickness(dTargetLeft, Indicator.Margin.Top, Indicator.Margin.Right, Indicator.Margin.Bottom);
                    }
                    else {
                        if (bModeToRight) {
                            Indicator.Margin = new Thickness(Indicator.Margin.Left + dIndicatorVelocity, Indicator.Margin.Top, Indicator.Margin.Right, Indicator.Margin.Bottom);
                        }
                        else {
                            Indicator.Margin = new Thickness(Indicator.Margin.Left - dIndicatorVelocity, Indicator.Margin.Top, Indicator.Margin.Right, Indicator.Margin.Bottom);
                        }
                    }
                }
            }
        }
    }
}
